from flask import Blueprint, jsonify, request, g, current_app
from flask_jwt_extended import jwt_required, get_jwt_identity, current_user

from backend.decorators import admin_required
from backend.models import db, User, Property
from backend.utils import format_response, api_response
from werkzeug.security import check_password_hash
import uuid  # 如果允许用户重新生成 apikey

users_bp = Blueprint('users', __name__)

def validate_user_data(data, is_create=False):
    """用户数据验证工具"""
    errors = {}

    # 创建时的特殊验证
    if is_create:
        if not data.get('username'):
            errors['username'] = "用户名不能为空"
        if not data.get('password'):
            errors['password'] = "密码不能为空"
        if not data.get('role'):
            errors['role'] = "必须指定用户角色"

    return errors or None


@users_bp.route('/', methods=['GET'])
@jwt_required()
@admin_required
@format_response
def get_users():
    """获取所有用户（仅管理员）"""
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('pageSize', 20, type=int)
    per_page = min(per_page, 100)  # Limit page size
    if page <= 0: page = 1
    if per_page <= 0: per_page = 20

    query = User.query
    if username_query := request.args.get('username', '', type=str):
        query = query.filter(User.username.like(f"%{username_query}%"))

    # 按 ID 排序
    users_pagination = query.order_by(User.id.asc()).paginate(
        page=page,
        per_page=per_page,
        error_out=False
    )

    result_data = {
        "list": [user_to_dict(u) for u in users_pagination.items], # 使用 user_to_dict 辅助函数
        "pagination": {
            "current_page": page,
            "per_page": per_page,
            "total_items": users_pagination.total,
            "total_pages": users_pagination.pages
        }
    }
    return result_data, 200


# 创建新用户（仅管理员）
@users_bp.route('/', methods=['POST'])
@jwt_required()
@admin_required
@format_response
def create_user():
    """创建新用户（仅管理员）"""
    data = request.get_json()
    if not data:
        return api_response(code=400, message="请求体不能为空")

    # 基础验证
    required_fields = ['username', 'password', 'role']
    if not all(field in data for field in required_fields):
        return api_response(code=400, message="缺少必要字段: username, password, role")

    # 角色验证 (可以限制允许创建的角色)
    allowed_roles = ['admin', 'public']  # 示例
    if data['role'] not in allowed_roles:
        return api_response(code=400, message=f"无效的角色，只允许: {', '.join(allowed_roles)}")

    # 唯一性检查
    if User.query.filter_by(username=data['username']).first():
        return {"error": "用户名已存在"}, 409

    # 创建用户
    try:
        new_user = User(
            username=data['username'],
            role=data['role'],
            # 管理员可以设置初始配额，否则使用模型默认值
            quota=data.get('quota', User.quota.default.arg),
            # 管理员可以设置初始 apikey，否则自动生成
            apikey=data.get('apikey', str(uuid.uuid4()))
        )
        new_user.set_password(data['password'])

        # 检查生成的 API Key 是否唯一 (如果管理员没提供)
        if not data.get('apikey'):
            while User.query.filter_by(apikey=new_user.apikey).first():
                new_user.apikey = str(uuid.uuid4())  # 重新生成直到唯一


        db.session.add(new_user)
        db.session.commit()

        return user_to_dict(new_user), 201 # 返回创建的用户信息和 201 状态码
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error creating user: {e}", exc_info=True)
        return api_response(code=500, message=f"创建用户时数据库出错: {e}")


#  更新用户（仅管理员）
@users_bp.route('/<int:user_id>', methods=['PUT'])
@jwt_required()
@admin_required
@format_response
def update_user(user_id):
    target_user = User.query.get_or_404(user_id)

    data = request.get_json()
    if not data:
        return api_response(code=400, message="请求体不能为空")

    try:
        # 更新用户名 (检查唯一性)
        if 'username' in data and data['username'] != target_user.username:
            if User.query.filter(User.id != user_id, User.username == data['username']).first():
                return api_response(code=409, message="用户名已存在")
            target_user.username = data['username']

        # 更新密码
        if 'password' in data and data['password']:  # 确保密码不为空
            target_user.set_password(data['password'])

        # 更新角色
        if 'role' in data:
            allowed_roles = ['admin', 'public']  # 示例
            if data['role'] not in allowed_roles:
                return api_response(code=400, message=f"无效的角色，只允许: {', '.join(allowed_roles)}")
            target_user.role = data['role']

        # 更新配额
        if 'quota' in data:
            try:
                target_user.quota = int(data['quota']) if data['quota'] is not None else None
            except (ValueError, TypeError):
                return api_response(code=400, message="配额必须是整数或 null")

        # 更新API Key (检查唯一性)
        if 'apikey' in data and data['apikey'] != target_user.apikey:
            if User.query.filter(User.id != user_id, User.apikey == data['apikey']).first():
                return api_response(code=409, message="API Key已存在")
            target_user.apikey = data['apikey']

        db.session.add(target_user)
        db.session.commit()
        return user_to_dict(target_user), 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error updating user {user_id}: {e}", exc_info=True)
        return api_response(code=500, message=f"更新用户时数据库出错: {e}")


# 删除用户（仅管理员）
@users_bp.route('/users/<int:user_id>', methods=['DELETE'])
@jwt_required()
@admin_required
@format_response
def delete_user_by_admin(user_id): # 重命名以区分
    """删除指定ID的用户（仅管理员）"""
    target_user = User.query.get(user_id)
    if not target_user:
        return api_response(code=404, message="用户未找到")

    # 检查是否在删除自己 (通常不允许)
    jwt_user_id = get_jwt_identity()
    if str(target_user.id) == jwt_user_id:
        return api_response(code=403, message="不能删除自己")

    try:
        # 处理关联 Property数据 (如果 Property.created_by 外键允许 NULL)
        Property.query.filter_by(created_by=target_user.id).update({'created_by': None})

        db.session.delete(target_user)
        db.session.commit()
        return {"message": "用户已删除"}, 200 # 使用字典，让 @format_response 包装
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error deleting user {user_id}: {e}", exc_info=True)
        return api_response(code=500, message=f"删除用户时数据库出错: {e}")


# --- 公众用户个人信息管理接口 ---

@users_bp.route('/me', methods=['GET'])
@jwt_required() # 任何登录用户都可以访问
@format_response
def get_current_user_info():
    """获取当前登录用户的信息"""
    # current_user 由 @jwt_required 和 user_lookup_loader 加载
    if not current_user:
         # 理论上 @jwt_required 会处理，但以防万一
         return api_response(code=401, message="无法加载用户信息")
    # 返回不敏感的信息
    user_data = {
        'id': current_user.id,
        'username': current_user.username,
        'role': current_user.role,
        'apikey': current_user.apikey,
        'quota': current_user.quota  # 不直接返回 apikey 和 quota，除非明确需要
    }
    return user_data, 200

@users_bp.route('/me', methods=['PUT'])
@jwt_required() # 任何登录用户都可以修改自己的信息
@format_response
def update_current_user_info():
    """更新当前登录用户的信息（例如修改密码）"""
    if not current_user:
         return api_response(code=401, message="无法加载用户信息")

    data = request.get_json()
    if not data:
        return api_response(code=400, message="请求体不能为空")

    try:
        # 允许用户修改用户名 (检查唯一性)
        if 'username' in data and data['username'] != current_user.username:
            if User.query.filter(User.id != current_user.id, User.username == data['username']).first():
                return api_response(code=409, message="用户名已存在")
            current_user.username = data['username']

        # 允许用户修改密码 (需要提供旧密码验证)
        if 'password' in data and 'old_password' in data:
            if not data['password']:
                 return api_response(code=400, message="新密码不能为空")
            if check_password_hash(current_user.password, data['old_password']):
                current_user.set_password(data['password'])
            else:
                return api_response(code=401, message="旧密码错误")
        elif 'password' in data and 'old_password' not in data:
             # 如果提供了新密码但没提供旧密码
             return api_response(code=400, message="修改密码需要提供旧密码 (old_password)")


        # 通常不允许用户自己修改 role, apikey, quota
        # 如果需要允许重新生成 apikey，可以添加逻辑

        db.session.add(current_user)
        db.session.commit()
        # 返回更新后的用户信息（不含敏感信息）
        user_data = {
            'id': current_user.id,
            'username': current_user.username,
            'role': current_user.role,
        }
        return user_data, 200
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Error updating current user info: {e}", exc_info=True)
        return api_response(code=500, message=f"更新用户信息时数据库出错: {e}")


@users_bp.route('/me/apikey', methods=['GET'])
@jwt_required() # 任何登录用户都可以查看自己的 API Key
@format_response
def get_my_apikey():
    """获取当前登录用户的 API Key"""
    if not current_user:
         return api_response(code=401, message="无法加载用户信息")

    # 确保用户对象有关联的 API Key
    if not current_user.apikey:
         # 可能需要在这里为没有 Key 的用户生成一个？或者提示错误
         current_user.apikey = str(uuid.uuid4())
         try:
            db.session.add(current_user)
            db.session.commit()
            current_app.logger.info(f"Generated API Key for user {current_user.username}")
         except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Failed to generate API Key for user {current_user.username}: {e}", exc_info=True)
            return api_response(code=500, message="获取 API Key 时出错")


    return {'apikey': current_user.apikey}, 200


def user_to_dict(user):
    return {
        'id': user.id,
        'username': user.username,
        'role': user.role,
        'quota': user.quota,
        'apikey': user.apikey
    }
